#include <iostream>
#include <string>
#include <functional>
#include <cassert>
#include <cstdio>
#include <pthread.h>
#include <unistd.h>

using namespace std;

class Thread;

struct Context
{
    Context()
    : _this(nullptr),
      _args(nullptr)
    {}

    Thread* _this;
    void* _args;
};

class Thread
{
public:
    typedef function<void*(void*)> func;

    static void* start_routine(void* args)
    {
        Context* cxt = (Context*)args;
        cxt->_this->_f(cxt->_this->_args);
        delete cxt;
        return nullptr;
    }

    Thread(func f, void* args, int number)
    : _f(f), 
      _args(args),
      _number(number)
    {
        char name[64];
        snprintf(name, sizeof name, "thread%d", number);
        _name = name;
        Context* cxt = new Context;
        cxt->_this = this;
        cxt->_args = _args;
        pthread_t tid;
        int n = pthread_create(&tid, nullptr, start_routine, cxt);
        assert(n == 0);
        (void)n;
        _tid = tid;
    }

    int join()
    {
        int n = pthread_join(_tid, nullptr);
        assert(n == 0);
        (void)n;
    }

private:
    string _name;
    func _f;
    void* _args;
    int _number;
    pthread_t _tid;
};